package com.dylan.shot.common.util;

import org.apache.commons.codec.DecoderException;
import org.apache.commons.codec.binary.Hex;
import org.apache.commons.codec.digest.DigestUtils;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.io.UnsupportedEncodingException;
import java.security.GeneralSecurityException;
import java.security.SecureRandom;

/**
 * 加密/解密工具
 */
public class EncryptUitl {

    /**
     * 使用AES加密，并生成16进制字符串
     * @param content 待加密的字符串
     * @param key 加密的KEY
     * @return 加密后的16进制字符串
     */
    public static String aesEncryptToHex(String content, String key) {
        byte[] originalEncrypt = aesOriginalEncrypt(content, key);
        return Hex.encodeHexString(originalEncrypt);
    }

    /**
     * 使用AES从16进制字符串解密
     * @param content 待解密的16进制字符串
     * @param key 加密时使用的KEY
     * @return 解密后的字符串
     */
    public static String aesDecryptFromHex(String content, String key) {
        try {
            byte[] originalDecrypt = Hex.decodeHex(content.toCharArray());
            return aesOriginalDecrypt(originalDecrypt, key);
        } catch (DecoderException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 使用MD5加密，并生成16进制的消息摘要
     * @param content 待加密的字符串
     * @return 加密后的16进制消息摘要
     */
    public static String md5HexDigest(String content) {
        return DigestUtils.md5Hex(content);
    }

    /**
     * 使用SHA1加密，并生成16进制的消息摘要
     * @param content 待加密的字符串
     * @return 加密后的16进制消息摘要
     */
    public static String sha1HexDigest(String content) {
        return DigestUtils.sha1Hex(content);
    }


    /**
     * 使用SHA256加密，并生成16进制的消息摘要
     * @param content 待加密的字符串
     * @return 加密后的16进制消息摘要
     */
    public static String sha256Hex(String content) {
        return DigestUtils.sha256Hex(content);
    }

    private static byte[] aesOriginalEncrypt(String content, String key) {
        try {
            KeyGenerator kgen = KeyGenerator.getInstance("AES");
            SecureRandom sr = SecureRandom.getInstance("SHA1PRNG");
            sr.setSeed(key.getBytes());
            kgen.init(128, sr);
            SecretKey secretKey = kgen.generateKey();
            byte[] enCodeFormat = secretKey.getEncoded();
            SecretKeySpec sk = new SecretKeySpec(enCodeFormat, "AES");
            Cipher cipher = Cipher.getInstance("AES");// 创建密码器
            byte[] byteContent = content.getBytes("UTF-8");
            cipher.init(Cipher.ENCRYPT_MODE, sk);// 初始化
            return cipher.doFinal(byteContent);// 加密
        } catch (GeneralSecurityException | UnsupportedEncodingException e) {
            throw new RuntimeException(e);
        }
    }

    private static String aesOriginalDecrypt(byte[] content, String key) {
        try {
            KeyGenerator kgen = KeyGenerator.getInstance("AES");
            SecureRandom sr = SecureRandom.getInstance("SHA1PRNG");
            sr.setSeed(key.getBytes());
            kgen.init(128, sr);
            SecretKey secretKey = kgen.generateKey();
            byte[] enCodeFormat = secretKey.getEncoded();
            SecretKeySpec sk = new SecretKeySpec(enCodeFormat, "AES");
            Cipher cipher = Cipher.getInstance("AES");// 创建密码器
            cipher.init(Cipher.DECRYPT_MODE, sk);// 初始化
            byte[] result = cipher.doFinal(content);
            return new String(result, "UTF-8");// 加密
        } catch (GeneralSecurityException | UnsupportedEncodingException e) {
            throw new RuntimeException(e);
        }
    }

    public static void main(String[] args) {
//        String content = "苹果是这种模式的始作俑者，也通过商业模式的变革给信息产业的发展充足了动力，但是，这种模式本身也存在很多问题，直接的后果就是不同的开发者和不同类型的应用条块分隔，手机上经常需要安装同类的不同类的大大小小的应用，增加了硬件的负担，给消费者的使用体验也造成了影响。" +
//                "\r\n因此，Facebook和微软都不断的暗示，应用的未来前景正变得暗淡，模拟人类互动的聊天机器人、软件编程才是新兴趋势。除了竞争对手之间的战略战术之外，也有希望借助弯道超车的机会颠覆苹果模式的想法和做法。";
//        String encryptContent = aesEncryptToHex(content, "cygw");
//        String decryptContent = aesDecryptFromHex(encryptContent, "cygw");
//        System.out.println("加密前:" + content);
//        System.out.println("加密后:" + encryptContent);
//        System.out.println("解密后:" + decryptContent);
//        System.out.println("加密/解密前后是否相同:" + content.equals(decryptContent));
//        System.out.println("MD5加密后:" + md5HexDigest(content));
//        System.out.println("SHA1加密后:" + sha1HexDigest(content));
//        System.out.println(System.currentTimeMillis()/1000);
    }
}
